﻿using SmartMotion.Core;
using Sunny.UI;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;

namespace SmartMotion.Pages.DockPages
{
    public partial class FrmCreateTool : UIForm
    {
        #region 字段

        private readonly string _groupName;
        private List<string> _dllList;
        private List<Type> _allType;
        private List<Type> _searchType;
        private List<MethodInfo> _allmethods;
        private List<MethodInfo> _searchMethods;
        private ActionItem _customTool;

        #endregion 字段

        public FrmCreateTool(string groupName)
        {
            _groupName = groupName;

            InitializeComponent();
        }

        private void FrmCreateTool_Load(object sender, EventArgs e)
        {
            _customTool = new ActionItem();
            RefreshDllAndIcon();

            var groups = ToolMgr.Ins.Tools.Select(tool => tool.Group).ToList().Distinct().ToList();
            cmbGroup.Items.AddRange(groups.ToArray());
            cmbGroup.Text = _groupName;
            ilsbIcon.SelectedIndex = 0;
        }

        private void RefreshDllAndIcon()
        {
            _dllList = new List<string>();
            var files = Directory.GetFiles(Environment.CurrentDirectory, "*.dll");
            lsbDll.Items.Clear();
            foreach (var file in files)
            {
                lsbDll.Items.Add(Path.GetFileName(file));
                _dllList.Add(Path.GetFileName(file));
            }

            var fileIcon = Directory.GetFiles(Environment.CurrentDirectory + "\\Tools\\", "*.png");
            ilsbIcon.Items.Clear();
            ilsbIcon.ItemHeight = 65;
            foreach (var s in fileIcon)
            {
                ilsbIcon.AddImage((Bitmap)Image.FromFile(s), Path.GetFileName(s));
            }
        }

        private void lsbDll_SelectedIndexChanged(object sender, EventArgs e)
        {
            string fileName = Environment.CurrentDirectory + "\\" + lsbDll.SelectedItem;
            var curDll = Assembly.LoadFile(fileName);
            var types = curDll.GetTypes();
            _allType = types.ToList();
            _searchType = types.ToList();
            var bs = new BindingSource();
            bs.DataSource = _searchType;
            lsbTypes.DataSource = bs;
            lsbTypes.DisplayMember = "Name";
        }

        private void txtSearchDll_TextChanged(object sender, EventArgs e)
        {
            lsbDll.Items.Clear();
            string txtSearch = txtSearchDll.Text;
            foreach (var dll in _dllList.Where(dll => dll.ToLower().Contains(txtSearch.ToLower())))
            {
                lsbDll.Items.Add(dll);
            }
        }

        private void lsbTypes_SelectedIndexChanged(object sender, EventArgs e)
        {
            var type = lsbTypes.SelectedItem as Type;
            if (type == null) return;
            _allmethods = type.GetMethods().ToList();
            _searchMethods = type.GetMethods().ToList();
            var bs = new BindingSource();
            bs.DataSource = _searchMethods;
            lsbMethods.DataSource = bs;
            lsbMethods.DisplayMember = "signature";
        }

        private void txtSearchType_TextChanged(object sender, EventArgs e)
        {
            string txtSearch = txtSearchType.Text;
            _searchType.Clear();
            foreach (var type in _allType.Where(type => type.Name.ToLower().Contains(txtSearch)))
            {
                _searchType.Add(type);
            }
            var bs = new BindingSource();
            bs.DataSource = _searchType;
            lsbTypes.DataSource = bs;
            lsbTypes.DisplayMember = "Name";
        }

        private void lsbMethods_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (lsbMethods.SelectedItem is MemberInfo method)
            {
                txtNewTool.Text = method.Name;
                //todo
            }
        }

        private void txtSearchMethod_TextChanged(object sender, EventArgs e)
        {
            string txtSearch = txtSearchMethod.Text;
            _searchMethods.Clear();
            foreach (var methodInfo in _allmethods)
            {
                if (methodInfo.Name.ToLower().Contains(txtSearch))
                {
                    _searchMethods.Add(methodInfo);
                }
            }
            var bs = new BindingSource();
            bs.DataSource = _searchMethods;
            lsbMethods.DataSource = bs;
            lsbMethods.DisplayMember = "signature";
        }

        private void btnRefresh_Click(object sender, EventArgs e)
        {
            RefreshDllAndIcon();
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            Type tp = lsbTypes.SelectedItem as Type;

            if (typeof(ActionItem).IsAssignableFrom(tp))
            {
                if (tp?.FullName != typeof(ActionItem).FullName)
                {
                    _customTool = (ActionItem)Activator.CreateInstance(tp);
                }
            }

            _customTool.Dll = lsbDll.SelectedItem.ToString();
            _customTool.TypeName = (lsbTypes.SelectedItem as Type)?.FullName;
            _customTool.ItemName = txtNewTool.Text;
            _customTool.Icon = ilsbIcon.SelectedItem.Description;
            _customTool.Group = cmbGroup.Text;

            if (lsbMethods.SelectedItem is MethodInfo method)
            {
                _customTool.MethodName = method.Name;
                _customTool.IsStatic = method.IsStatic;
                _customTool.ReturnType = method.ReturnType.FullName;
                var methodParams = method.GetParameters();
                foreach (var parameterInfo in methodParams)
                {
                    _customTool.ParaTypes.Add(parameterInfo.ParameterType.FullName);
                    _customTool.ParaNames.Add(parameterInfo.Name);
                    _customTool.Parms.Add(new MethodParms() { Name = parameterInfo.Name, Type = parameterInfo.ParameterType.FullName });
                }
                ToolMgr.Ins.SaveTools(_customTool);
                Close();
            }
        }
    }
}